package com.sinosoft.common.encrypt.filter;

import com.sinosoft.common.encrypt.properties.ApiDecryptProperties;
import com.sinosoft.common.encrypt.utils.CryptoUtils;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.nio.charset.StandardCharsets;

import java.io.*;

/**
 * 解密请求体包装器
 */
public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {
    
    private final ApiDecryptProperties properties;
    private String decryptedBody;
    
    public DecryptRequestBodyWrapper(HttpServletRequest request, ApiDecryptProperties properties) {
        super(request);
        this.properties = properties;
        decryptRequestBody();
    }
    
    private void decryptRequestBody() {
        try {
            // 读取原始请求体
            StringBuilder sb = new StringBuilder();
            try (BufferedReader reader = getReader()) {
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            }
            String encryptedBody = sb.toString();
            
            // 获取加密密钥头
            String encryptKey = getHeader("X-Encrypt-Flag");
            if (encryptKey == null || encryptKey.isEmpty()) {
                throw new RuntimeException("缺少加密密钥头");
            }
            
            // 使用SM2私钥解密SM4密钥
            String sm4Key = CryptoUtils.decryptSm4Key(encryptKey, properties.getSm2PrivateKey());

            // 使用SM4密钥解密请求体
            this.decryptedBody = CryptoUtils.decryptBody(encryptedBody, sm4Key);
            
        } catch (Exception e) {
            throw new RuntimeException("请求体解密失败: " + e.getMessage());
        }
    }
    
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new ServletInputStream() {
            private final ByteArrayInputStream bais = new ByteArrayInputStream(
                decryptedBody != null ? decryptedBody.getBytes(StandardCharsets.UTF_8) : new byte[0]
            );
            
            @Override
            public int read() throws IOException {
                return bais.read();
            }
            
            @Override
            public boolean isFinished() {
                return bais.available() == 0;
            }
            
            @Override
            public boolean isReady() {
                return true;
            }
            
            @Override
            public void setReadListener(jakarta.servlet.ReadListener readListener) {
                // 不需要实现
            }
        };
    }
    
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(getInputStream(), "UTF-8"));
    }
} 